/* eslint-disable */
import Vue from 'vue' 
import { on, off } from '../utils/dom'
import { transferIndex, transferIncrease } from '../utils/transfer-queue'
const isServer = Vue.prototype.$isServer
const isSafariBrowser = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)
//在popper.js源码中新增了 setOptions方法，请勿更改引用方式或将此方法覆盖
import PopperJs from '../utils/popper'
const Popper = isServer ? function(){} : PopperJs
const prefixCls ="zz-tooltip"
const refClass = `${prefixCls}-directive-reference`

let rect = {}
const referenceObj = {
  getBoundingClientRect: function() {
    return rect
  },
  get clientWidth(){
    return rect.width
  },
  get clientHeight(){
    return rect.height
  }
}

const options ={
  placement: "bottom"
}
// 随机id存储tooltip
const __tooltipRef = {}
const getRandomStr =() => {
  const id = Math.random().toString(36).substr(2)
  if(id in __tooltipRef) {
    return getRandomStr()
  }
  return id
}

let __refId = ''
const $tooltip = document.createElement('div')
document.body.appendChild($tooltip)

const $tooltipComp = new Vue({ 
  data(){
    return {
      content: '',
      sourceData: null,
      mouseoverRef: false,
      mouseoverPop:false,
      maxWidth:null,
      maxHeight:null,
      theme: 'light',
      popperClass: '',
      zIndex:0,
      refTimer: null
    }
  },
  methods:{
    resetTimer(time = 50) {
      this.clearTimer()
      this.refTimer = setTimeout(()=>{
        this.mouseoverRef = false
      },time)
    },
    clearTimer(){
      if(this.refTimer){
        clearTimeout(this.refTimer)
      }
    }
  },
  beforeDestroy(){
    this.clearTimer()
  },
  computed:{
    isPopperShow(){
      return this.mouseoverRef || this.mouseoverPop
    }
  },
  
  render: function(h){
    return h(
      'transition',
      {
        attrs:{
          name: 'fade'
        }
      },
      [
        h(
          'div',
          {
            class: {
              [`${prefixCls}-popper`]: true,
              [`${prefixCls}-${this.theme}`]: true,
              [`${this.popperClass}`]: true
            },
            style: {
              display: this.isPopperShow ? '' : 'none',
              zIndex: this.zIndex,
              top: 0,
              left: this.isPopperShow ? '-110%' : '-100%'
            },
            on: {
              mouseenter: ()=> {
                this.mouseoverPop = true
              },
              mouseleave: () => {
                setTimeout(() => {
                  this.mouseoverPop = false
                }, 5)
              }
            }
          },
          [
            h('div',
              {
                class: {
                  [`${prefixCls}-content`]: true
                }
              },
              [
                h('div', {
                  class: {
                    [`${prefixCls}-arrow`]: true
                  }
                }),
                h(
                  'div',
                  {
                    ref: 'popInner',
                    class: {
                      [`${prefixCls}-inner`]: true
                    },
                    style: {
                      maxWidth: this.maxWidth ? `${this.maxWidth}px` : '',
                      maxHeight: this.maxHeight ? `${this.maxHeight}px` : ''
                    },
                    on: {
                      mousewheel: e => {
                        // 阻止事件冒泡
                        e.stopPropagation()
                        const { scrollTop, offsetHeight, scrollHeight } = e.target
                        // 如果内容区不可滚动，阻止滚动事件
                        if (offsetHeight === scrollHeight) {
                          return e.preventDefault()
                        }
                        // 如果内容区可滚动，判断滚动方向 及 是否滚动到顶部/底部
                        const isUp = e.wheelDelta ? e.wheelDelta > 0 : e.detail < 0
                        isPrevent = false
                        if (isUp) {
                          isPrevent = scrollTop <= 0
                        } else {
                          isPrevent = scrollTop + offsetHeight >= scrollHeight
                        }
                        isPrevent && e.preventDefault()
                      }
                    }
                  },
                  typeof this.content === 'function' ? [this.content(h, { sourceData: this.sourceData })] : this.content
                )
              ]
            )
          ]
        )
      ]
    )
  },
  watch: {
    isPopperShow(val) {
      if(val) {
        transferIncrease()
        this.zIndex = 11060 + transferIndex
      } else {
        this.popperClass = ''
        this.$refs.popInner.scrollTop = 0
      }
    }
  }
}).$mount($tooltip)

const createPopper= function(el,popper, options){
  const { placement, offset, eventExpand, positionFixed } = options 
  return new Popper(el, popper, {
    placement: placement || "bottom",
    modifiers:{
      computeStyle:{
        gpuAcceleration: false
      },
      preventOverflow:{
        boundariesElement: 'window'
      },
      offset:{
        offset:offset || 0
      },
      eventExpand: eventExpand || true,
      positionFixed: positionFixed || false
    }
  })
}
const popper =createPopper(referenceObj, $tooltipComp.$el,options) 

let positionTimer = null

const validatePlacement = function (placement){
  return /^(top|bottom|left|right)(-start|-end)?$/g.test(placement)
}
  
  //v3.3.18 修复边界情况时，出现省略号，鼠标移入不出现tooltip
  // @Params {el}被克隆的目标dom
  // @Returns{rectCopy}克隆元素的getBoundingClientRect()

  const getElementRect = function (el){
    const style = getComputedStyle(el)
    const isInput = el.tagName.toLowerCase()==='input'
    if(isInput){
      const text = el.value || el.getAttribute('placeholder')
      el = document.createElement('div')
      el.innerHTML=text
    }else {
      el =el.cloneNode(true);
    }
    el.style.display = 'inline';
    el.style.width = "auto";
    el.style.visibility ="hidden";
    el.style.fontSize = style.fontSize;
    el.style.fontFamily = style.fontFamily;
    el.style.fontWeight = style.fontWeight;
    el.style.letterSpacing = style.letterSpacing;
    el.style.wordSpacing = style.wordSpacing;
    el.style.padding = style.padding
    el.style.border = style.border
    el.style.boxSizing = style.boxSizing
    document.body.appendChild(el)
    const rectCopy = el.getBoundingClientRect()
    document.body.removeChild(el);
    return rectCopy;
  }
  //判断元素是否超出
  export const noEllipsis = function(el) {
    // copy 元素，获取自然填充时的宽度
    const { width: scrollWidth } = getElementRect(el)
    //获取元素实际宽度，不用offsetWidth，是因为Chrome调整缩放比例对offsetWidth有影响
    const { width: offsetWidth }= el.getBoundingClientRect()//兼容 IE，临界值有偏差
    return scrollWidth - offsetWidth <= 0.001
  }

  const handleMouseEnter = function (event){
    const tooltip = event.target.getAttribute('data-tooltip')
    let tooltipOptions =__tooltipRef[tooltip].options
    const { judgeWidth = true, placement, content, maxWidth, maxHeight, theme, popperClass, delay = 100, sourceData, disabled = false } = tooltipOptions
    if(!validatePlacement(placement)){
      return
    }

    if(disabled){
      return
    }

    if(judgeWidth && noEllipsis(event.target)) {
      return
    }
    
    popper.setOptions(tooltipOptions)
    rect =event.target.getBoundingClientRect()
    $tooltipComp.$data.mouseoverRef = true
    $tooltipComp.$data.content =content
    $tooltipComp.$data.sourceData = sourceData
    $tooltipComp.$data.maxWidth = maxWidth
    $tooltipComp.$data.maxHeight = maxHeight
    $tooltipComp.$data.theme = theme || 'light'
    $tooltipComp.$data.popperClass = popperClass || ''
    __refId = tooltip
    $tooltipComp.clearTimer()
    positionTimer = setTimeout(() => { 
      popper.scheduleUpdate()
    }, delay)
  }
    
const handleMouseleave = function () {
  if(positionTimer){
    clearTimeout(positionTimer)
  }
  $tooltipComp.resetTimer()
}
      
const hideTooltip= function (tooltip, refId) {
  if(tooltip === refId){
      $tooltipComp.$data.mouseoverRef = false
      $tooltipComp.$data.mouseoverPop = false
  }
}
    
// fix 页面滚动时，tooltip不消失
const handleMousewheel = function (e){
  $tooltipComp.resetTimer(0)
}


window.addEventListener("mousewheel", handleMousewheel)

export default {
    bind(el,{ value }){
    const tooltip = getRandomStr()
    const { disabled = false } = value
    el.setAttribute('data-tooltip', tooltip)
    if(!disabled){
      el.classList.add(refClass)
    }
    if(isSafariBrowser){
      el.classList.add('zz-safari-title-hidden')
    }
    __tooltipRef[tooltip]= {
      options:{
        placement:'bottom',
        ...value
      }
    }
    hideTooltip(tooltip, __refId)
    on(el,'mouseenter', handleMouseEnter)
    on(el,'mouseleave', handleMouseleave)
  },
  update(el, { value }) {
    const tooltip = el.getAttribute('data-tooltip')
    const { disabled = false } = value
    if(!disabled){
      el.classList.add(refClass)
    } else {
      el.classList.remove(refClass)
      handleMouseleave()
    }
    __tooltipRef[tooltip].options = {
      placement:'bottom',
      ...value
    }
  },
  unbind(el){
    const tooltip = el.getAttribute('data-tooltip')
    hideTooltip(tooltip, __refId)
    off(el,'mouseenter',handleMouseEnter)
    off(el,'mouseleave',handleMouseleave)
    delete __tooltipRef[tooltip]
  }
}